local H = require "packages/new_heg/util"
local HC = require "packages/new_hegcomplements/util"
local U = require "packages/utility/utility"
local extension = Package:new("mobileheg")
extension.extensionName = "new_hegcomplements"
extension.game_modes_whitelist = { 'ex_heg_mode', 'mul_heg_mode' }

Fk:loadTranslationTable {
  ["mobileheg"] = "手杀",
  ["m_hc_heg"] = "手杀",
}

local xiahoudun = General(extension, "m_hc_heg__n_xiahoudun", "wei", 4)
local ganglie = fk.CreateTriggerSkill{
  name = "m_hc__ganglie",
  anim_type = "masochism",
  events = {fk.Damaged},
  on_trigger = function(self, event, target, player, data)
    self.cancel_cost = false
    for i = 1, data.damage do
      if i > 1 and (self.cancel_cost or not player:hasSkill(self)) then break end
      self:doCost(event, target, player, data)
    end
  end,
  on_cost = function(self, event, target, player, data)
    local room = player.room
    if data.from and not data.from.dead then
      if room:askForSkillInvoke(player, self.name, data, "#m_hc__ganglie-invoke::"..data.from.id) then
        room:doIndicate(player.id, {data.from.id})
        return true
      end
    else
      if room:askForSkillInvoke(player, self.name, data) then
        return true
      end
    end
    self.cancel_cost = true
  end,
  on_use = function(self, event, target, player, data)
    local room = player.room
    local from = data.from
    if from and not from.dead then room:doIndicate(player.id, {from.id}) end
    local judge = {
      who = player,
      reason = self.name,
      pattern = ".",
    }
    room:judge(judge)
    if not from or from.dead then return false end
    if judge.card.color == Card.Red then
      room:damage{
        from = player,
        to = from,
        damage = 1,
        skillName = self.name,
      }
    elseif judge.card.color == Card.Black and not from:isNude() and not player.dead then
      local cid = room:askForCardChosen(player, from, "he", self.name)
      room:throwCard({cid}, self.name, from, player)
    end
  end
}

xiahoudun:addSkill(ganglie)
Fk:loadTranslationTable{
  ["m_hc_heg__n_xiahoudun"] = "夏侯惇",
  ["#m_hc_heg__n_xiahoudun"] = "独眼的罗刹",
  ["illustrator:m_hc_heg__n_xiahoudun"] = "DH",

  ["m_hc__ganglie"] = "刚烈",
  [":m_hc__ganglie"] = "当你受到1点伤害后，你可判定，若结果为：红色，你对来源造成1点伤害；黑色，你弃置来源的一张牌。",

  ["#m_hc__ganglie-invoke"] = "是否对%dest发动 刚烈，判红对其造成伤害，判黑弃其牌",

  ["$m_hc__ganglie1"] = "哪个敢动我！",
  ["$m_hc__ganglie2"] = "伤我者，十倍奉还！",
  ["~m_hc_heg__n_xiahoudun"] = "诸多败绩，有负丞相重托。",
}

local xushu = General(extension, "m_hc_heg__n_xushu", "shu", 4)
xushu.deputyMaxHpAdjustedValue = -1

local zhuhai = fk.CreateTriggerSkill{
  name = "m_hc__zhuhai",
  events = {fk.EventPhaseStart},
  anim_type = "offensive",
  can_trigger = function(self, event, target, player, data)
    return player:hasSkill(self) and player ~= target and target.phase == Player.Finish and not target.dead and
    #player.room.logic:getActualDamageEvents(1, function(e)
      return e.data[1].from == target
    end, Player.HistoryTurn) > 0
  end,
  on_cost = function (self, event, target, player, data)
    local use = player.room:askForUseCard(player, self.name, "slash", "#m_hc__zhuhai-ask::"..target.id, true,
      {bypass_times = true, bypass_distances = true, extraUse = true, must_targets = {target.id}})
    if use then
      self.cost_data = use
      return true
    end
  end,
  on_use = function(self, event, target, player, data)
    local use = self.cost_data
    local room = player.room
    if #room.logic:getActualDamageEvents(1, function (e)
      return e.data[1].from == target and H.compareKingdomWith(player, e.data[1].to)
    end, Player.HistoryTurn) > 0 then
      use.extra_data = use.extra_data or {}
      use.extra_data.mzhuhaitarget = target.id
    end
    room:useCard(use)
  end,
}

local zhuhai_delay = fk.CreateTriggerSkill{
  name = "#m_hc__zhuhai_delay",
  mute = true,
  frequency = Skill.Compulsory,
  events = {fk.CardUseFinished},
  anim_type = "offensive",
  can_trigger = function(self, event, target, player, data)
    return player == target and data.card.trueName == "jink" and (data.responseToEvent.extra_data or {}).mzhuhaitarget == player.id and
      table.find(player:getCardIds("he"), function (id) return not player:prohibitDiscard(Fk:getCardById(id)) end)
  end,
  on_use = function(self, event, target, player, data)
    player.room:askForDiscard(player, 1, 1, true, zhuhai.name, false)
  end,

  refresh_events = {fk.PreCardUse},
  can_refresh = function(self, event, target, player, data)
    return player == target and data.card.trueName == "slash" and (data.extra_data or {}).mzhuhaitarget ~= nil
  end,
  on_refresh = function(self, event, target, player, data)
    local room = player.room
    data.extra_data = data.extra_data or {}
    local to = room:getPlayerById(data.extra_data.mzhuhaitarget)
    room:addPlayerMark(to, fk.MarkArmorNullified)
    room.logic:getCurrentEvent():findParent(GameEvent.UseCard, true):addExitFunc(function ()
      room:removePlayerMark(to, fk.MarkArmorNullified)
    end)
  end,
}

--其实就是个不显示数量的武将牌库
Fk:addQmlMark{
  name = "mjiancai_mark",
  qml_path = function(name, value, p)
    if Self == p then
      return "packages/new_hegcomplements/qml/mjiancai"
    end
    return ""
  end,
  how_to_show = function(name, value, p)
    return " "
  end,
}

local jiancai = fk.CreateTriggerSkill{
  name = "m_hc__jiancai",
  mute = true,
  relate_to_place = "d",
  events = {fk.DamageInflicted, fk.GeneralRevealed, fk.RoundStart},
  can_trigger = function (self, event, target, player, data)
    if not player:hasSkill(self) then return end
    if event == fk.DamageInflicted then
      return H.compareKingdomWith(player, target) and data.damage >= target.hp
    elseif event == fk.GeneralRevealed then
      if target == player then
        for _, v in pairs(data) do
          if table.contains(Fk.generals[v]:getSkillNameList(), self.name) then return true end
        end
      end
    else
      return true
    end
  end,
  on_cost = function (self, event, target, player, data)
    if event == fk.DamageInflicted then
      if player.room:askForSkillInvoke(player, self.name, data, "#m_hc__jiancai-ask::"..target.id) then
        self.cost_data = {tos = {target.id}}
        return true
      end
    else
      self.cost_data = {}
      return true
    end
  end,
  on_use = function (self, event, target, player, data)
    local room = player.room
    if event ~= fk.DamageInflicted then
      room:notifySkillInvoked(player, self.name)
      player:broadcastSkillInvoke(self.name)
      local hasgenerals = player:getTableMark("@[mjiancai_mark]")
      local x = room:getBanner("RoundCount")*3 - #hasgenerals
      if x <= 0 then return end
      local kingdom = player:getMark("__heg_kingdom")
        if kingdom == "wild" then
          kingdom = player:getMark("__heg_init_kingdom")
        end
      local shugenerals = table.filter(room.general_pile, function (g) return not table.contains(hasgenerals, g)
        and (Fk.generals[g].kingdom == kingdom or Fk.generals[g].subkingdom == kingdom)
      end)
      local gets = table.random(shugenerals, x)
      table.insertTableIfNeed(hasgenerals, gets)
      room:setPlayerMark(player, "@[mjiancai_mark]", hasgenerals)
    else
      player:broadcastSkillInvoke(self.name)
      room:notifySkillInvoked(player, self.name, "big")
      if player:getMark("@@m_hc__jiancai_transform") > 0 then return true end
      if #player:getTableMark("@[mjiancai_mark]") == 0 or H.isBigKingdomPlayer(player) and not table.find(room.alive_players, function(p)
        return H.isBigKingdomPlayer(p) and H.compareKingdomWith(player, p, true) end) then
        room:setPlayerMark(player,"@@m_hc__jiancai_transform", 1)
        H.transformGeneral(room, player)
        return true
      else
        local jiancaigeneral = {}
        local result = player.room:askForCustomDialog(player, self.name,
        "packages/utility/qml/ChooseGeneralsAndChoiceBox.qml", {
          player:getTableMark("@[mjiancai_mark]"),
          {"OK"},
          "#m_hc__jiancai-trans",
          {"Cancel"},
          1,
          3
        })
        if result ~= "" then
          local reply = json.decode(result)
          if reply.choice == "OK" then
            jiancaigeneral = reply.cards
          end
        end
        room:setPlayerMark(player,"@@m_hc__jiancai_transform", 1)
        local transformdata = {
          isMain = false,
          isHidden = false,
          num = 3,
        }
        if room.logic:trigger("fk.GeneralTransforming", player, transformdata) then return false end
        local isMain = transformdata.isMain
        local isHidden = transformdata.isHidden
        local num = transformdata.num
        local orig = isMain and player.general or player.deputyGeneral
        num = num or 3
        if not orig then return false end
        if orig == "anjiang" then
          player:revealGeneral(not isMain, true)
          orig = isMain and player.general or player.deputyGeneral
        end
        local existingGenerals = {}
        for _, p in ipairs(room.players) do
          table.insert(existingGenerals, H.getActualGeneral(p, false))
          table.insert(existingGenerals, H.getActualGeneral(p, true))
        end
        local kingdom = player:getMark("__heg_kingdom")
        if kingdom == "wild" then
          kingdom = player:getMark("__heg_init_kingdom")
        end
        local generals = {}
        for _, g in ipairs(jiancaigeneral) do
          if table.contains(room.general_pile, g) then
            room:findGeneral(g)
            table.insert(generals, g)
          end
        end
        if #generals < num then
          local othergenerals = room:findGenerals(function(g)
            return Fk.generals[g].kingdom == kingdom or Fk.generals[g].subkingdom== kingdom
          end, num - #generals)
          table.insertTableIfNeed(generals, othergenerals)
        end
        if #generals == 0 then return end
        local general = room:askForGeneral(player, generals, 1, true) ---@type string
        table.removeOne(generals, general)
        if not orig:startsWith("blank_") then
          table.insert(generals, orig)
        end
        room:returnToGeneralPile(generals)
        if not isHidden then
          room:changeHero(player, general, false, not isMain, true, false, false)
        else
          if isMain then
            room:setPlayerGeneral(player, "anjiang", true)
            local general = Fk.generals[player:getMark("__heg_general")]
            local skills = table.connect(general.skills, table.map(general.other_skills, Util.Name2SkillMapper))
            for _, s in ipairs(skills) do
              if s.relate_to_place ~= "d" then
                H.addHegSkill(player, s, room)
              end
            end
          else
            room:setDeputyGeneral(player, "anjiang")
            local deputy = Fk.generals[player:getMark("__heg_deputy")]
            if deputy then
              local skills = table.connect(deputy.skills, table.map(deputy.other_skills, Util.Name2SkillMapper))
              for _, s in ipairs(skills) do
                if s.relate_to_place ~= "m" then
                  H.addHegSkill(player, s, room)
                end
              end
            end
          end
        end
        room:setPlayerMark(player, isMain and "__heg_general" or "__heg_deputy", general)
        if not isHidden then
          room:changeHero(player, general, false, not isMain, true, false, false)
        else
          -- 暗置变更 --FIXME,等主服修
          local lose = Fk.generals[orig]
          local general = isMain and Fk.generals[player:getMark("__heg_general")] or
          Fk.generals[player:getMark("__heg_deputy")]
          room:setPlayerGeneral(player, "anjiang", isMain)
          local skills = table.connect(general.skills, table.map(general.other_skills, Util.Name2SkillMapper))
          local location = isMain and "d" or "m"
          for _, s in ipairs(skills) do
            if s.relate_to_place ~= location then
              H.addHegSkill(player, s, room)
            end
          end
          for _, s in ipairs(lose:getSkillNameList()) do
            room:handleAddLoseSkills(player, "-" .. s, nil)
          end
        end
        room.logic:trigger("fk.GeneralTransformed", player, orig)
        return true
      end
    end
  end,

  on_lose = function (self, player, is_death)
    local room = player.room
    room:setPlayerMark(player, "@[mjiancai_mark]", 0)
  end,
}

zhuhai:addRelatedSkill(zhuhai_delay)
xushu:addSkill(zhuhai)
xushu:addSkill(jiancai)

xushu:addCompanions("hs__n_zhaoyun")
xushu:addCompanions("hs__n_wolong")

Fk:loadTranslationTable{
  ["m_hc_heg__n_xushu"] = "徐庶",
  ["#m_hc_heg__n_xushu"] = "难为完臣",
  ["illustrator:m_hc_heg__n_xushu"] = "YanBai",

  ["m_hc__zhuhai"] = "诛害",
  [":m_hc__zhuhai"] = "其他角色的结束阶段，若其本回合造成过伤害，你可以对其使用一张【杀】。若其本回合对与你势力相同的角色造成过伤害，此【杀】无视其防具，且当其使用【闪】响应此【杀】后，其弃置一张牌。",
  ["#m_hc__zhuhai_delay"] = "诛害",
  ["m_hc__jiancai"] = "荐才",
  [":m_hc__jiancai"] = "副将技，此武将牌上减少1个单独的阴阳鱼。当你明置此武将牌后或每轮开始时，你获知的未登场同势力武将牌增加至X张（X为轮次数*3）。"
    .."当与你势力相同的角色受到致命伤害时，你可以防止此伤害，然后你变更副将；若你所属的势力不为唯一大势力，此次变更副将你可以优先从你获知的武将中选择。",

  ["@[mjiancai_mark]"] = "荐才",
  ["@@m_hc__jiancai_transform"] = "荐才 已变更",
  ["#m_hc__zhuhai-ask"] = "诛害：你可对 %dest 使用【杀】",
  ["#m_hc__jiancai-ask"] = "你想对 %dest 发动〖荐才〗吗？",
  ["#m_hc__jiancai-trans"] = "荐才：你可以选择至多三张武将牌，优先作为备选武将牌",

  ["$m_hc__zhuhai1"] = "今日当要替天行道！",
  ["$m_hc__zhuhai2"] = "我容得你，天不容你！",
  ["$m_hc__jiancai1"] = "得此贤士，如鱼得水。",
  ["$m_hc__jiancai2"] = "将军，在下可举荐一人。",
  ["~m_hc_heg__n_xushu"] = "未尽孝道，抱憾此生。",
}

local lifeng = General(extension, "m_hc_heg__lifeng", "shu", 3)
local tunchu = fk.CreateTriggerSkill{
  name = "m_hc__tunchu",
  anim_type = "drawcard",
  relate_to_place = "m",
  derived_piles = "m_hc__liang",
  events = {fk.DrawNCards, fk.AfterDrawNCards},
  can_trigger = function(self, event, target, player, data)
    if target == player then
      if event == fk.DrawNCards then
        return player:hasSkill(self) and #player:getPile("m_hc__liang") == 0
      else
        return player:usedSkillTimes(self.name, Player.HistoryPhase) > 0 and not player:isKongcheng()
      end
    end
  end,
  on_cost = function(self, event, target, player, data)
    if event == fk.DrawNCards then
      return player.room:askForSkillInvoke(player, self.name)
    else
      local cards = player.room:askForCard(player, 1, 999, false, self.name, true, ".", "#m_hc__tunchu-put")
      if #cards > 0 then
        self.cost_data = cards
        return true
      end
    end
  end,
  on_use = function(self, event, target, player, data)
    if event == fk.DrawNCards then
      data.n = data.n + 2
    else
      player:addToPile("m_hc__liang", self.cost_data, true, self.name)
    end
  end,
}
local tunchu_prohibit = fk.CreateProhibitSkill{
  name = "#tunchu_prohibit",
  prohibit_use = function(self, player, card)
    return player:hasShownSkill(tunchu) and #player:getPile("m_hc__liang") > 0 and card.trueName == "slash"
  end,
}
local shuliang = fk.CreateTriggerSkill{
  name = "m_hc__shuliang",
  anim_type = "support",
  relate_to_place = "m",
  expand_pile = "m_hc__liang",
  events = {fk.EventPhaseStart},
  can_trigger = function(self, event, target, player, data)
    return player:hasSkill(self) and target.phase == Player.Finish and target:getHandcardNum() < target.hp and
    #player:getPile("m_hc__liang") > 0
  end,
  on_cost = function(self, event, target, player, data)
    local card = player.room:askForCard(player, 1, 1, false, self.name, true,
      ".|.|.|m_hc__liang|.|.", "#m_hc__shuliang-invoke::"..target.id, "m_hc__liang")
    if #card > 0 then
      self.cost_data = card
      return true
    end
  end,
  on_use = function(self, event, target, player, data)
    local room = player.room
    room:doIndicate(player.id, {target.id})
    room:moveCards({
      from = player.id,
      ids = self.cost_data,
      toArea = Card.DiscardPile,
      moveReason = fk.ReasonPutIntoDiscardPile,
      skillName = self.name,
      specialName = self.name,
    })
    if not target.dead then
      target:drawCards(2, self.name)
    end
  end,
}
tunchu:addRelatedSkill(tunchu_prohibit)
lifeng:addSkill(tunchu)
lifeng:addSkill(shuliang)
Fk:loadTranslationTable{
  ["m_hc_heg__lifeng"] = "李丰",
  ["#m_hc_heg__lifeng"] = "朱提太守",
  ["illustrator:m_hc_heg__lifeng"] = "NOVART",

  ["m_hc__tunchu"] = "屯储",
  [":m_hc__tunchu"] = "主将技，摸牌阶段，若你没有“粮”，你可以多摸两张牌，然后可以将任意张手牌置于你的武将牌上，称为“粮”；若你的武将牌上有“粮”，你不能使用【杀】。",
  ["m_hc__shuliang"] = "输粮",
  [":m_hc__shuliang"] = "主将技，一名角色结束阶段，若其手牌数小于其体力值，你可以移去一张“粮”，然后其摸两张牌。",
  ["m_hc__liang"] = "粮",
  ["#m_hc__tunchu-put"] = "屯储：你可以将任意张手牌置为“粮”",
  ["#m_hc__shuliang-invoke"] = "输粮：你可以移去一张“粮”，令 %dest 摸两张牌",

  ["$m_hc__tunchu1"] = "屯粮事大，暂不与尔等计较。",
  ["$m_hc__tunchu2"] = "屯粮待战，莫动刀枪。",
  ["$m_hc__shuliang1"] = "将军驰劳，酒肉慰劳。",
  ["$m_hc__shuliang2"] = "将军，牌来了。",
  ["~m_hc_heg__lifeng"] = "吾，有负丞相重托。",
}

local lukang = General(extension, "m_hc_heg__n_lukang", "wu", 3, 3, General.Male)
local keshou_filter = fk.CreateActiveSkill{
  name = "#m_hc__keshou_filter",
  min_card_num = 2,
  max_card_num = 2,
  card_filter = function(self, to_select, selected, player)
    if table.contains(player:getCardIds("e"), to_select) then return end
    return table.every(selected, function(id)
      return Fk:getCardById(to_select).color == Fk:getCardById(id).color
    end)
  end,
  target_filter = Util.FalseFunc,
  can_use = Util.FalseFunc,
}
local keshou = fk.CreateTriggerSkill{
  name = "m_hc__keshou",
  anim_type = "defensive",
  events = {fk.DamageInflicted},
  can_trigger = function (self, event, target, player, data)
    return player:hasSkill(self) and player == target
  end,
  on_use = function (self, event, target, player, data)
    local room = player.room
    if #target:getCardIds("h") > 1 then
      local result, dat = room:askForUseActiveSkill(player, "#m_hc__keshou_filter", "#m_hc__keshou:::" .. data.damage, true)
      if result then
        room:throwCard(dat.cards, self.name, player, player)
        data.damage = data.damage - 1
      end
    end
    if player and not player.dead and H.getKingdomPlayersNum(room)[H.getKingdom(player)] == 1 then
      local judge = {
        who = player,
        reason = self.name,
        pattern = ".|.|heart,diamond|.|.|.",
      }
      room:judge(judge)
      if judge.card.color == Card.Red and not player.dead then
        player:drawCards(1, self.name)
      end
    end
  end,
}
keshou:addRelatedSkill(keshou_filter)

local zhuwei = fk.CreateTriggerSkill{
  name = "m_hc__zhuwei",
  anim_type = "drawcard",
  events = {fk.FinishJudge},
  can_trigger = function(self, event, target, player, data)
    return target == player and player:hasSkill(self) 
      and player.room:getCardArea(data.card) == Card.Processing
  end,
  on_use = function(self, event, target, player, data)
    local room = player.room
    room:obtainCard(player.id, data.card, true, fk.ReasonJustMove)
    local current = room.current
    local choices = {"m_hc__zhuwei_ask::" .. current.id, "Cancel"}
    if room:askForChoice(player, choices, self.name) ~= "Cancel" then
      room:addPlayerMark(current, "@m_hc__zhuwei_buff-turn", 1)
      room:addPlayerMark(current, MarkEnum.AddMaxCardsInTurn, 1)
    end
  end,
}

local zhuwei_targetmod = fk.CreateTargetModSkill{
  name = "#m_hc__zhuwei_targetmod",
  residue_func = function(self, player, skill, scope)
    if skill.trueName == "slash_skill" and player:getMark("@m_hc__zhuwei_buff-turn") > 0 and scope == Player.HistoryPhase then
      return player:getMark("@m_hc__zhuwei_buff-turn")
    end
  end,
}

lukang:addSkill(keshou)
zhuwei:addRelatedSkill(zhuwei_targetmod)
lukang:addSkill(zhuwei)
lukang:addCompanions("hs__n_luxun")
Fk:loadTranslationTable{
  ["m_hc_heg__n_lukang"] = "陆抗",
  ["#m_hc_heg__n_lukang"] = "孤柱扶厦",
  ["illustrator:m_hc_heg__n_lukang"] = "王立雄",
  ["m_hc__keshou"] = "恪守",
  [":m_hc__keshou"] = "当你受到伤害时，你可发动此技能：你可弃置两张颜色相同的手牌，令此伤害值-1。若没有与你势力相同的其他角色，你判定，若结果为红色，你摸一张牌。",
  ["#m_hc__keshou"] = "恪守：是否弃置两张颜色相同的牌，令你受到的%arg点伤害-1",
  ["m_hc__zhuwei"] = "筑围",
  [":m_hc__zhuwei"] = "当你的判定结果确定后，你可获得此判定牌，然后你可令当前回合角色手牌上限和使用【杀】的次数上限于此回合内+1。",
  ["m_hc__zhuwei_ask"] = "令%dest手牌上限和使用【杀】的次数上限于此回合内+1",
  ["@m_hc__zhuwei_buff-turn"] = "筑围",

  ["#m_hc__keshou_filter"] = "恪守",

  ["$m_hc__keshou1"] = "仁以待民，自处不败之势。",
  ["$m_hc__keshou2"] = "宽济百姓，则得战前养备之机。",
  ["$m_hc__zhuwei1"] = "背水一战，只为破敌。",
  ["$m_hc__zhuwei2"] = "全线并进，连战克晋。",
  ["~m_hc_heg__n_lukang"] = "抗仅以君子之交待叔子，未有半分背国之念啊……",
}

local lingcao = General(extension, "m_hc_heg__lingcao", "wu", 4)
local dujin = fk.CreateTriggerSkill{
  name = "m_hc__dujin",
  anim_type = "drawcard",
  relate_to_place = "m",
  events = {fk.DrawNCards},
  on_use = function(self, event, target, player, data)
    data.n = data.n + 1 + #player:getCardIds(Player.Equip) // 2
  end,
}

lingcao:addSkill(dujin)

Fk:loadTranslationTable{
  ["m_hc_heg__lingcao"] = "凌操",
  ["#m_hc_heg__lingcao"] = "激流勇进",
  ["illustrator:m_hc_heg__lingcao"] = "樱花闪乱",
  ["m_hc__dujin"] = "独进",
  [":m_hc__dujin"] = "主将技，摸牌阶段，你可以多摸X+1张牌（X为你装备区内牌数的一半，向下取整）。",
  ["$m_hc__dujin1"] = "带兵十万，不如老夫多甲一件！",
  ["$m_hc__dujin2"] = "轻舟独进，破敌先锋！",
  ["~m_hc_heg__lingcao"] = "呃啊！（扑通）此箭……何来……",
}

local zuoci = General(extension, "m_hc_heg__n_zuoci", "qun", 3)

local function GetSoul(player, n)
  local room = player.room
  local generals = room:findGenerals(function () return true end, n)
  local mark = U.getPrivateMark(player, "&m_hc__soul")
  table.insertTableIfNeed(mark, generals)
  U.setPrivateMark(player, "&m_hc__soul", mark)
  if #player:getTableMark("m_hc__yigui_cards") == 0 then
    room:setPlayerMark(player, "m_hc__yigui_cards", U.getUniversalCards(room, "bt"))
  end
end

local jihun = fk.CreateTriggerSkill{
  name = "m_hc__jihun",
  anim_type = "masochism",
  events = {fk.Damaged, fk.AfterDying},
  can_trigger = function(self, event, target, player, data)
    if event == fk.Damaged then
    return player:hasSkill(self) and target == player
    elseif event == fk.AfterDying then
      return player:hasSkill(self) and target and not target.dead and H.compareKingdomWith(target, player)
    end
  end,
  on_use = function(self, event, target, player, data)
    GetSoul(player, 1)
  end,
}

local function canbeTargetedbySoul(to, name)
  local kingdoms, general = {}, Fk.generals[name]
  if general then
    table.insertIfNeed(kingdoms, general.kingdom)
    if general.subkingdom then
      table.insertIfNeed(kingdoms, general.subkingdom)
    end
  end
  local tokingdom = to.kingdom
  --仿照手杀，触发建国后，1.加入的人不算野；2.无论是否有人加入，野人都不算野
  if tokingdom == "wild" and to:getMark("_wild_final_end") + to:getMark("__heg_join_wild") + to:getMark("__heg_construct_wild") > 0 then
    tokingdom = to.role
  end
  return tokingdom == "unknown" or tokingdom == "wild" or table.contains(kingdoms, tokingdom)
end

local function getAvailableSoul(player)
  local souls = U.getPrivateMark(player, "&m_hc__soul")
  if #souls == 0 then return {} end
  if table.find({"jink", "nullification", "heg__nullification"}, function (name) return Fk.currentResponsePattern
    and Exppattern:Parse(Fk.currentResponsePattern):match(Fk:cloneCard(name)) end) then
    return souls
  end
  local players, availables = {}, {}
  local extra_data = player:getTableMark("m_hc__yigui_extra_data")
  if extra_data.fix_targets then
    table.insertTableIfNeed(players, extra_data.fix_targets)
  elseif extra_data.must_targets then
    table.insertTableIfNeed(players, extra_data.must_targets)
  elseif extra_data.exclusive_targets then
    table.insertTableIfNeed(players, extra_data.exclusive_targets)
  elseif extra_data.include_targets then
    table.insertTableIfNeed(players, extra_data.include_targets)
  end
  if #players == 0 then
    players = Fk.currentRoom(player).alive_players
  else
    players = table.map(players, Util.Id2PlayerMapper)
  end
  for _, s in ipairs(souls) do
    if table.find(players, function (p) return canbeTargetedbySoul(p, s) end) then
      table.insert(availables, s)
    end
  end
  return availables
end

local function getFightTogethercanUseMethod(player, skill_name, soul)
  local card, cheakcard = Fk:cloneCard("fight_together"), Fk:cloneCard("fight_together")
  card.skillName = skill_name
  card:setMark("m_hc__yigui", soul)
  local ret = {}
  if not table.find(Fk.currentRoom(player).alive_players, function (p) return H.isBigKingdomPlayer(p)
    and player:isProhibited(p, card) ~= player:isProhibited(p, cheakcard) end) then
    table.insert(ret, "big")
  end
  if not table.find(Fk.currentRoom(player).alive_players, function (p) return H.isSmallKingdomPlayer(p)
    and player:isProhibited(p, card) ~= player:isProhibited(p, cheakcard) end) then
    table.insert(ret, "small")
  end
  return ret
end

local function getAvailableYiguiCard(player, skill_name, card_names, souls)
  souls = souls or getAvailableSoul(player)
  card_names = card_names or table.map(player:getTableMark("m_hc__yigui_cards"), function (id) return Fk:getCardById(id).name end)
  if #card_names == 0 then return {} end
  local ban_cards = player:getTableMark("m_hc__yigui_useds-turn")
  local extra_data = player:getTableMark("m_hc__yigui_extra_data")
  local names = {}
  for _, name in ipairs(card_names) do
    local card = Fk:cloneCard(name)
    if (Fk.currentResponsePattern == nil or Exppattern:Parse(Fk.currentResponsePattern):match(card))
      and not table.contains(ban_cards, card.trueName) then
      card.skillName = skill_name
      for _, soul in ipairs(souls) do
        card:setMark("m_hc__yigui", soul)
        if (player:canUse(card, extra_data) or (Fk.currentResponsePattern ~= nil and table.contains({"jink", "nullification", "heg__nullification"}, name)))
          and not player:prohibitUse(card) then
          local min_target = card.skill:getMinTargetNum()
          if min_target > 0 then
            if card.trueName == "fight_together" then
              if #getFightTogethercanUseMethod(player, skill_name, soul) > 0 then
                table.insertIfNeed(names, name)
                goto continue
              end
            else
              for _, p in pairs(Fk.currentRoom(player).alive_players) do
                if card.skill:targetFilter(p.id, {}, {}, card, extra_data, player) then
                  table.insertIfNeed(names, name)
                  goto continue
                end
              end
            end
          else
            if card.multiple_targets then
              local cheakcard = Fk:cloneCard(name)
              if #card:getAvailableTargets(player, extra_data) == #cheakcard:getAvailableTargets(player, extra_data) then
                table.insertIfNeed(names, name)
                goto continue
              end
            else
              table.insertIfNeed(names, name)
              goto continue
            end
          end
        end
      end
    end
    ::continue::
  end
  return names
end

local yigui = fk.CreateViewAsSkill{
  name = "m_hc__yigui",
  mute = true,
  pattern = ".|.|.|.|.|basic,trick",
  expand_pile = function(self, player)
    return player:getTableMark("m_hc__yigui_cards")
  end,
  interaction = function(self, player)
    local souls = U.getPrivateMark(player, "&m_hc__soul")
    local availables = getAvailableSoul(player)
    if #availables == 0 then return false end
    return HC.GeneralCardNameBox { choices = availables, all_choices = souls }
  end,
  card_filter = function(self, to_select, selected, player)
    if #selected > 0 or not table.contains(player:getTableMark("m_hc__yigui_cards"), to_select) then return false end
    local name = Fk:getCardById(to_select).name
    local cardnames = getAvailableYiguiCard(player, self.name, {name}, {self.interaction.data})
    return table.contains(cardnames, name)
  end,
  view_as = function(self, cards, player)
    if #cards == 0 or not self.interaction.data then return end
    local name = Fk:getCardById(cards[1]).name
    local card = Fk:cloneCard(name)
    card.skillName = self.name
    card:setMark("m_hc__yigui", self.interaction.data)
    if card.trueName == "fight_together" then
      card:setMark("m_hc__yigui_ft", getFightTogethercanUseMethod(player, self.name, self.interaction.data))
    end
    return card
  end,
  enabled_at_play = function(self, player)
    return #getAvailableSoul(player) > 0
  end,
  enabled_at_response = function(self, player, response)
    return #getAvailableSoul(player) > 0 and not response and #getAvailableYiguiCard(player, self.name) > 0
  end,
}

local yigui_show = fk.CreateTriggerSkill{
  name = "#m_hc__yigui_show",
  main_skill = yigui,
  events = {fk.GeneralRevealed},
  can_trigger = function(self, event, target, player, data)
    if target ~= player or not player:hasSkill(self.main_skill) or player:getMark("m_hc__yigui_show") > 0 then return false end
    for _, v in pairs(data) do
      if table.contains(Fk.generals[v]:getSkillNameList(), yigui.name) then return true end
    end
  end,
  on_cost = Util.TrueFunc,
  on_use = function(self, event, target, player, data)
    player:broadcastSkillInvoke(yigui.name)
    player.room:setPlayerMark(player, "m_hc__yigui_show", 1)
    GetSoul(player, 2)
  end,

  refresh_events = {fk.HandleAskForPlayCard ,fk.PreCardUse},
  can_refresh = function(self, event, target, player, data)
    if #U.getPrivateMark(player, "&m_hc__soul") == 0 then return false end
    if event == fk.HandleAskForPlayCard then
      return data.user == player
    elseif event == fk.PreCardUse then
      return player == target and table.contains(data.card.skillNames, yigui.name)
    end
  end,
  on_refresh = function(self, event, target, player, data)
    local room = player.room
    if event == fk.PreCardUse then
      room:notifySkillInvoked(player, yigui.name)
      player:broadcastSkillInvoke(yigui.name)
      room:addTableMark(player, "m_hc__yigui_useds-turn", data.card.trueName)
      local mark = U.getPrivateMark(player, "&m_hc__soul")
      table.removeOne(mark, data.card:getMark("m_hc__yigui"))
      room:returnToGeneralPile({data.card:getMark("m_hc__yigui")})
      if #mark == 0 then
        room:setPlayerMark(player, "@[private]&m_hc__soul", 0)
      else
        U.setPrivateMark(player, "&m_hc__soul", mark)
      end
      room:sendLog{
        type = "#m_hc__yigui-use",
        from = player.id,
        --arg = data.card:getMark("m_hc__yigui"), --手杀不公布来着
        arg2 = data.card.name,
        toast = true,
      }
      data.extra_data = data.extra_data or {}
      data.extra_data.m_hc__yigui = data.card:getMark("m_hc__yigui") -- 往extra_data里备份一份魂的信息，防止扇子杀变火杀后信息丢失
    else
      room:setPlayerMark(player, "m_hc__yigui_extra_data", data.afterRequest and 0 or data.extraData)
    end
  end,

  on_lose = function (self, player, is_death)
    local room = player.room
    room:returnToGeneralPile(U.getPrivateMark(player, "&m_hc__soul"))
    room:setPlayerMark(player, "@[private]&m_hc__soul", 0)
  end,
}

local yigui_prohibit = fk.CreateProhibitSkill{
  name = "#m_hc__yigui_prohibit",
  frequency = Skill.Compulsory,
  is_prohibited = function(self, from, to, card)
    if card and table.contains(card.skillNames, yigui.name) then
      if card.trueName == "fight_together" and #card:getTableMark("m_hc__yigui_ft") > 0 then
        if H.isBigKingdomPlayer(to) and not table.contains(card:getTableMark("m_hc__yigui_ft"), "big") or
          H.isSmallKingdomPlayer(to) and not table.contains(card:getTableMark("m_hc__yigui_ft"), "small") then
          return true
        end
      end
      local general = card:getMark("m_hc__yigui")
      if not general then
        if RoomInstance then -- 丢失魂信息则寻找备用信息
          local logic = RoomInstance.logic
          local event = logic:getCurrentEvent():findParent(GameEvent.UseCard, true)
          if event then
            local use = event.data[1]
            if table.contains(use.card.skillNames, yigui.name) and use.card.name == card.name then
              use.extra_data = use.extra_data or {}
              general = use.extra_data.m_hc__yigui
            end
          end
        end
      end
      return general and not canbeTargetedbySoul(to, general)
    end
  end,
}

yigui:addRelatedSkill(yigui_show)
yigui:addRelatedSkill(yigui_prohibit)
zuoci:addSkill(yigui)
zuoci:addSkill(jihun)
zuoci:addCompanions("ld__n_yuji")

Fk:loadTranslationTable{
  ["m_hc_heg__n_zuoci"] = "左慈",
  ["#m_hc_heg__n_zuoci"] = "鬼影神道",
  ["illustrator:m_hc_heg__n_zuoci"] = "吕阳",

  ["#m_hc__yigui_show"] = "役鬼",
  ["m_hc__yigui"] = "役鬼",
  [":m_hc__yigui"] = "当你首次明置此武将牌后，你将两张未加入游戏的武将牌扣置于武将牌上，称为“魂”；"..
  "每回合每种牌名限一次，你可以移去一张“魂”，视为使用一张基本牌或普通锦囊牌，以此法使用的牌若需指定角色为目标，"..
  "则只能指定未确定势力、野心家或与此“魂”牌势力相同的角色为目标（不满足卡牌原本目标要求则无法使用）。",
  ["m_hc__jihun"] = "汲魂",
  [":m_hc__jihun"] = "当你受到伤害后或与你势力相同的角色进入濒死状态被救回后，你可以将一张未加入游戏的武将牌扣置加入到“魂”牌中。",

  ["@[private]&m_hc__soul"] = "魂",
  ["#m_hc__yigui-use"] = "%from 移去一张“魂”，视为使用 %arg2",

  ["$m_hc__yigui1"] = "世间万物，贫道皆可化为其形。",
  ["$m_hc__yigui2"] = "尘身土塑，唯魂魄难得。",
  ["$m_hc__jihun1"] = "大成若缺，损益无妨。",
  ["$m_hc__jihun2"] = "大盈若冲，心神自现。",
  ["~m_hc_heg__n_zuoci"] = "仙人之逝，魂归九天……",
}

local duyu = General(extension, "m_hc_heg__qunduyu", "qun", 4)

local wuku = fk.CreateTriggerSkill{
  name = "m_hc__wuku",
  events = {fk.CardUsing},
  frequency = Skill.Compulsory,
  can_trigger = function(self, event, target, player, data)
    return player:hasSkill(self) and player:getMark("@m_hc__wuku") < 2 and data.card.type == Card.TypeEquip and H.compareKingdomWith(player, target, true)
  end,
  on_use = function(self, event, target, player)
    player.room:addPlayerMark(player, "@m_hc__wuku")
  end,

  on_lose = function (self, player, is_death)
    player.room:setPlayerMark(player, "@m_hc__wuku", 0)
  end,
}

local miewu = fk.CreateViewAsSkill{
  name = "m_hc__miewu",
  mute = true,
  pattern = ".",
  handly_pile = true,
  interaction = function(self, player)
    local all_names = U.getAllCardNames("btd")
    local names = U.getViewAsCardNames(player, self.name, all_names)
    if #names == 0 then return false end
    return UI.ComboBox { choices = names, all_choices = all_names }
  end,
  card_filter = function(self, to_select, selected)
    return #selected == 0
  end,
  view_as = function(self, cards)
    if #cards ~= 1 or not self.interaction.data then return end
    local card = Fk:cloneCard(self.interaction.data)
    card:addSubcards(cards)
    card.skillName = self.name
    return card
  end,
  after_use = function(self, player, use)
    if not player.dead then
      player:drawCards(1, self.name)
    end
  end,
  enabled_at_play = function(self, player)
    return player:getMark("@m_hc__wuku") > 0 and player:usedSkillTimes(self.name) == 0
  end,
  enabled_at_response = function(self, player, response)
    return player:getMark("@m_hc__wuku") > 0 and player:usedSkillTimes(self.name) == 0 and Fk:currentRoom():getCurrent()
  end,
}

local miewu_delay = fk.CreateTriggerSkill{
  name = "#m_hc__miewu_delay",
  refresh_events = {fk.PreCardUse, fk.PreCardRespond},
  mute = true,
  frequency = Skill.Compulsory,
  can_refresh = function(self, event, target, player, data)
    return not player.dead and player == target and table.contains(data.card.skillNames, miewu.name)
  end,
  on_refresh = function(self, event, target, player, data)
    local room = player.room
    room:notifySkillInvoked(player, miewu.name)
    player:broadcastSkillInvoke(miewu.name)
    room:removePlayerMark(player, "@m_hc__wuku")
    if event == fk.PreCardRespond then
      local current = room.logic:getCurrentEvent()
      local responseevent = current:findParent(GameEvent.RespondCard, true)
      responseevent:addExitFunc(function()
        if not player.dead then
          player:drawCards(1, miewu.name)
        end
      end)
    end
  end,
}

duyu:addSkill(wuku)
miewu:addRelatedSkill(miewu_delay)
duyu:addSkill(miewu)

Fk:loadTranslationTable{
  ["m_hc_heg__qunduyu"] = "杜预",
  ["#m_hc_heg__qunduyu"] = "文成武德",
  ["illustrator:m_hc_heg__qunduyu"] = "鬼画府",
  ["m_hc__wuku"] = "武库",
  [":m_hc__wuku"] = "锁定技，与你势力不同的角色使用装备牌时，若你的“武库”标记数小于2，你获得1个“武库”标记。",
  ["@m_hc__wuku"] = "武库",
  ["m_hc__miewu"] = "灭吴",
  [":m_hc__miewu"] = "每回合限一次，你可以弃置1个“武库”并将一张牌当做任意基本牌或锦囊牌使用或打出，若如此做，你摸一张牌。",

  ["$m_hc__wuku1"] = "损益万枢，竭世运机。",
  ["$m_hc__wuku2"] = "胸藏万卷，充盈如库。",
  ["$m_hc__miewu1"] = "倾荡之势已成，石城尽在眼下。",
  ["$m_hc__miewu2"] = "吾军势如破竹，江东六郡唾手可得。",
  ["~m_hc_heg__qunduyu"] = "洛水圆石，遂道向南，吾将以俭自完耳……",
}

local zhanglu = General(extension, "m_hc_heg__n_zhanglu", "wei", 3)

local bushi = fk.CreateTriggerSkill{
  name = "m_hc__bushi",
  mute = true,
  events = {fk.TurnEnd, fk.EventPhaseStart},
  can_trigger = function(self, event, target, player, data)
    if not player:hasSkill(self) then return end
    if event == fk.TurnEnd then return target == player
    elseif target.phase == Player.Start then
      if target == player then
        return player:getMark("@m_hc__bushi_yishe") > 0 or ((#player.room.alive_players - player.hp - 2) > 0 and
          table.find(player:getCardIds("he"), function (id) return not player:prohibitDiscard(Fk:getCardById(id)) end))
      else
        return player:getMark("@m_hc__bushi_yishe") > 0 and #player:getCardIds("he") > 0 and not target.dead
      end
    end
  end,
  on_cost = function(self, event, target, player, data)
    if event == fk.TurnEnd or target == player then
      self.cost_data = {}
      return true
    else
      local cards = player.room:askForCard(player, 1, 1, true, self.name, true, ".", "#m_hc__bushi::" .. target.id)
      if #cards > 0 then
        self.cost_data = {tos = {target.id}, cards = cards}
        return true
      end
    end
  end,
  on_use = function(self, event, target, player)
    player:broadcastSkillInvoke(self.name)
    local room = player.room
    if event == fk.TurnEnd then
      room:notifySkillInvoked(player, self.name, "special")
      room:addPlayerMark(player, "@m_hc__bushi_yishe", player.hp)
    elseif target == player then
      local y = #room.alive_players - player.hp - 2
      room:notifySkillInvoked(player, self.name, "negative")
      if y > 0 then
        room:askForDiscard(player, y, y, true, self.name, false)
      end
      room:setPlayerMark(player, "@m_hc__bushi_yishe", 0)
    else
      room:notifySkillInvoked(player, self.name, "support", self.cost_data.tos)
      room:removePlayerMark(player, "@m_hc__bushi_yishe")
      room:obtainCard(target, self.cost_data.cards, false, fk.ReasonGive)
      if not player.dead then
        player:drawCards(2, self.name)
      end
    end
  end,

  on_lose = function (self, player, is_death)
    player.room:setPlayerMark(player, "@m_hc__bushi_yishe", 0)
  end,
}

local midao = fk.CreateTriggerSkill{
  name = "m_hc__midao",
  mute = true,
  derived_piles = "m_hc__midao_rice",
  events = {fk.EventPhaseStart, fk.AskForRetrial},
  can_trigger = function (self, event, target, player, data)
    if event == fk.EventPhaseStart then
      return player == target and player:hasSkill(self) and player.phase == Player.Finish and #player:getPile("m_hc__midao_rice") == 0
    elseif event == fk.AskForRetrial then
      return player:hasSkill(self) and #player:getPile("m_hc__midao_rice") > 0
    end
  end,
  on_cost = function (self, event, target, player, data)
    if event == fk.EventPhaseStart then
      return player.room:askForSkillInvoke(player, self.name)
    elseif event == fk.AskForRetrial then
      local card = player.room:askForCard(player, 1, 1, false, self.name, true, ".|.|.|m_hc__midao_rice", "#m_hc__midao-ask::" .. target.id .. ":" .. data.reason, "m_hc__midao_rice")
      if #card > 0 then
        self.cost_data = card[1]
        return true
      end
    end
  end,
  on_use = function (self, event, target, player, data)
    player:broadcastSkillInvoke(self.name)
    if event == fk.EventPhaseStart then
      player.room:notifySkillInvoked(player, self.name, "drawcard")
      player:drawCards(2, self.name)
      if player:isNude() then return end
      local cards
      if #player:getCardIds("he") < 3 then
        cards = player:getCardIds("he")
      else
        cards = player.room:askForCard(player, 2, 2, true, self.name, false, ".", "#m_hc__midao")
      end
      player:addToPile("m_hc__midao_rice", cards, true, self.name)
    elseif event == fk.AskForRetrial then
      player.room:notifySkillInvoked(player, self.name)
      player.room:retrial(Fk:getCardById(self.cost_data), player, data, self.name, true)
    end
  end,
}

zhanglu.subkingdom = "qun"
zhanglu:addSkill(bushi)
zhanglu:addSkill(midao)

Fk:loadTranslationTable{
  ["m_hc_heg__n_zhanglu"] = "张鲁",
  ["#m_hc_heg__n_zhanglu"] = "政宽教惠",
  ["illustrator:m_hc_heg__n_zhanglu"] = "磐蒲",

  ["m_hc__bushi"] = "布施",
  [":m_hc__bushi"] = "回合结束时，你获得X枚“义舍”（X为你的体力值）；其他角色的准备阶段，你可以弃1枚“义舍”并交给其一张牌，然后摸两张牌；"
    .. "准备阶段，你弃置Y张牌并移去所有“义舍”标记（Y为存活角色数-你的体力值-2）。",
  ["m_hc__midao"] = "米道",
  [":m_hc__midao"] = "结束阶段，若你没有“米”，你可以摸两张牌，然后将两张牌置于你的武将牌上，称为“米”；当一名角色的判定牌生效前，你可以打出一张“米”替换之。",

  ["@m_hc__bushi_yishe"] = "义舍",
  ["#m_hc__bushi"] = "布施：你可弃1枚“义舍”并交给 %dest 一张牌，然后摸两张牌",
  ["#m_hc__midao-ask"] = "米道：你可打出一张牌替换 %dest 的 %arg 判定",
  ["#m_hc__midao"] = "米道：请将两张牌置于武将牌上，称为“米”。",
  ["m_hc__midao_rice"] = "米",

  ["$m_hc__bushi1"] = "争斗，永远没有赢家。",
  ["$m_hc__bushi2"] = "和平，永远没有输家。",
  ["$m_hc__midao1"] = "恩结天地，法惠八荒。",
  ["$m_hc__midao2"] = "行五斗米道，可知暖饱。",
  ["~m_hc_heg__n_zhanglu"] = "唉，义不敌武，道难御兵……",
}

return extension
